package com.etxxy.remoting.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.etxxy.common.type.FilePathEnum;
import com.etxxy.common.type.FileSuffixEnum;
import com.etxxy.common.type.FileTypeEnum;
import com.etxxy.common.util.AESUtil;
import com.etxxy.common.util.UUIDHexGenerator;
import com.etxxy.file.FileService;

/**
 * @category 文件操作
 * @author yiz
 *
 */
@Service("fileService")
public class FileServiceImpl implements FileService {
	private static final Logger logger = LoggerFactory.getLogger(FileServiceImpl.class);
	@Value("${file.save.path}")
	private String path;

	@Value("${file.server.ip}")
	private String ip;

	@Value("${file.server.port}")
	private String port;

	@Value("${file.server.name}")
	private String name;

	private static final String AESKEY = "youneedsome%dfood";

	/**
	 * @category 图片文件上传
	 * @param bytes
	 * @param typeEnum
	 * @param imageTypeEnum
	 * @param suffixEnum
	 * @param downController 指定下载控制器
	 * @return
	 */
	@Override
	public String uploadFile(byte[] bytes, FileTypeEnum typeEnum, FilePathEnum filePathEnum, FileSuffixEnum suffixEnum,
			String downController) {
		String uuid = UUIDHexGenerator.generate();
		//文件路径
		StringBuffer filePath = new StringBuffer();
		filePath.append(path).append(typeEnum.name()).append("\\").append(filePathEnum.name());
		//文件名
		StringBuffer fileName = new StringBuffer();
		fileName.append(uuid).append(".").append(suffixEnum.name());
		//转成字节nio字节缓存
		ByteBuffer byteBuff = ByteBuffer.wrap(bytes);
		//nio保存文件
		saveFile(byteBuff, filePath.toString(), fileName.toString());
		//完整路径
		String fullFilePath = filePath.toString() + "\\" + fileName.toString();
		//
		String fileUrl = buildUrl(fullFilePath, downController);
		return fileUrl;
	}

	/**
	 * @category 文件下载，Controller对不同的请求进行不同的操作，返回字节流
	 */
	@Override
	public byte[] downloadFile(String fileName) {
		//解密出文件完整路径
		fileName = AESUtil.decryptPass(fileName, AESKEY);
		//读取出字节
		ByteBuffer byteBuffer = readFile(fileName);
		byte[] b = new byte[byteBuffer.remaining()];
		byteBuffer.get(b, 0, b.length);
		return b;
	}

	/**
	 * @category 构建下载链接地址
	 * @param fileName 文件路径（AES加密）
	 * @param controller 控制器
	 * @return
	 */
	private String buildUrl(String fileName, String controller) {
		StringBuffer url = new StringBuffer();
		url.append("http://").append(ip);
		if (!"80".equals(port)) {
			//非80端口增加端口显示
			url.append(":").append(port);
		}
		url.append("/").append(name).append("/").append(controller).append("/")
				.append(AESUtil.encryptPass(fileName, AESKEY));
		return url.toString();
	}

	/**
	 * @category 保存文件 
	 * @param byteBuff
	 * @param filePath
	 * @param filename
	 */
	private void saveFile(ByteBuffer byteBuff, String filePath, String filename) {
		FileChannel foChannel = null;
		FileOutputStream outputStream = null;
		File file = null;
		try {
			file = new File(filePath);
			if (!file.exists()) {
				file.mkdirs();
			}
			outputStream = new FileOutputStream(filePath + "\\" + filename);
			foChannel = outputStream.getChannel();
			foChannel.write(byteBuff);
		} catch (IOException e) {
			logger.error("IO异常e={}", e);
		} finally {
			try {
				if (null != outputStream) {
					outputStream.close();
				}
				if (null != foChannel) {
					foChannel.close();
					foChannel = null;
				}
			} catch (IOException e) {
				logger.error("关闭流异常e={}", e);
			}

		}
	}

	/**
	 * @category 读取文件
	 * @param filename
	 * @return
	 */
	private ByteBuffer readFile(String filename) {
		FileChannel fiChannel = null;
		MappedByteBuffer mBuf = null;
		FileInputStream inputStream = null;
		try {
			inputStream = new FileInputStream(filename);
			fiChannel = inputStream.getChannel();
			mBuf = fiChannel.map(FileChannel.MapMode.READ_ONLY, 0, fiChannel.size());
		} catch (FileNotFoundException e) {
			logger.error("文件不存在异常e={}", e);
		} catch (IOException e) {
			logger.error("IO异常e={}", e);
		} finally {
			try {
				if (null != inputStream) {
					inputStream.close();
				}
				if (null != fiChannel) {
					fiChannel.close();
					fiChannel = null;
				}
			} catch (IOException e) {
				logger.error("关闭流出现IO异常e={}", e);
			}
		}
		return mBuf;

	}
}
